/*
*	Created:			06.03.10
*	Author:				009
*	Last Modifed:		-
*/

// SDK
#include "SDK/amx/amx.h"
#include "SDK/plugincommon.h"
// os
#include "os.h"
// core
#include "math.h"
#include <stdio.h>
// plugin
#include "hooks.h"
#include "callbacks.h"
#include "main.h"
#include "Nodes.h"
// zmap
#include "ZMap.h"
// npc core
#include "NPC class.h"
// samp data
#include "samp address.h"
#include "samp defines.h"
#include "samp structs.h"

// main vars
extern DWORD		c_samp;
extern DWORD		c_players;
extern DWORD		CSampPointer;
// remote procedures pointers
extern f_ClientConnect			ClientConnectPointer;
extern f_ClientDisconnect		ClientDisconnectPointer;
extern f_SpawnForWorld			SpawnForWorldPointer;
extern f_SetSpawnInfoPointer	SetSpawnInfoPointer;
extern f_KillForWorld			KillForWorldPointer;
extern f_SetWeaponSkill			SetWeaponSkillPointer;

extern DWORD		CPlayerPosXOffset;
extern DWORD		CPlayerPosYOffset;
extern DWORD		CPlayerPosZOffset;
extern DWORD		CPlayerHealthOffset;
extern DWORD		CPlayerArmourOffset;
extern DWORD		CPlayerAngleOffset;
extern DWORD		CPlayerStateOffset;
extern DWORD		CPlayerFootSyncOffset;
extern DWORD		CPlayerInCarSyncOffset;
extern DWORD		CPlayerPassangerSyncOffset;
extern DWORD		CPlayerAimSyncOffset;
extern DWORD		CPlayerAimSyncStateOffset;
extern DWORD		CPlayerSyncTypeOffset;
extern DWORD		CPlayerWeaponSkillOffset;
extern DWORD		CPlayerSkinOffset;
extern DWORD		CPlayerInteriorOffset;
extern DWORD		CPlayerIsStreamedOffset;
extern DWORD		CPlayerVehicleIdOffset;
extern DWORD		CPlayerVehicleSeatOffset;

extern DWORD		CVehiclePosXOffset;
extern DWORD		CVehiclePosYOffset;
extern DWORD		CVehiclePosZOffset;
extern DWORD		CVehicleDriverOffset;
extern DWORD		CVehicleModelOffset;
extern DWORD		CVehicleHealthOffset;

extern	AMX*		gAMX;

extern	CZMap*		ZMap;

extern	float		WeaponsDamage[MAX_WEAPONS + 2];
extern	int			WeaponsReloadTime[MAX_WEAPONS + 1];
extern	int			WeaponReload[MAX_PLAYERS];

int	VisualDeath = 1;

bool IsInRange(float x,float y,float z,float range);

float Grad2Roll(float grad);
float Roll2Grad(float roll);

void quaternion_from_angles(Quaternion *q,float ax,float ay,float az );


CNPC::CNPC(int npcid,char* npcname)
{
	status = true;
	state = 0;
	myid = npcid;
	speed = 0.0;
	IsMoving = false;

	CALL_ARGS(c_players,ClientConnectPointer,npcid _ npcname _ 1);

	ResetStat();
}

CNPC::~CNPC()
{
	status = false;
	int tmp = myid;

	StopRecordingPlayback(NPC_RECORD_END_REASON_DESTROY);

	CALL_ARGS(c_players,ClientDisconnectPointer,tmp _ 1);
}

/*
	Name:	ResetStat
	Parameters in:
			-
	Parameters out:
			-
	Return:
			-
*/
void CNPC::ResetStat()
{
	// reset CPlayer
	c_player_struct = *(DWORD*)(c_players + (myid * 4) + C_PLAYERS_PLAYER_OFFSET);
	// reset spawn info
	int params[14];
	params[1] = myid;
	params[2] = 0;
	params[3] = 0;
	params[4] = 0;
	params[5] = 0;
	params[6] = 0;
	params[7] = 0;
	params[8] = 0;
	params[9] = 0;
	params[10] = 0;
	params[11] = 0;
	params[12] = 0;
	params[13] = 0;
	SetSpawnInfo(c_player_struct,params);
	// reset info
	SetPos(0.0,0.0,0.0);
	SetAngle(0.0);
	SetVelocity(0.0,0.0,0.0);
	SetKeys(0,0,0);
	SetSpecialAction(0);
	SetWeapon(0);
	SetSkin(0);
	SetSurfingVehicle(INVALID_VEHICLE_ID);
	SetVehicleRoll(0.0,0.0,0.0);
	SetVehicleVelocity(0.0,0.0,0.0);
	SetVehicleKeys(0,0,0);
	SetVehicleSiren(0);
	SetVehicleUnique(0);
	SetVehicleTrailer(INVALID_VEHICLE_ID);
	// health
	SetHealth(100.0);
	// armour
	SetArmour(0.0);
	// local vars
	impregnable = false;
	IsMoving = false;
	IsUseZMap = false;
	IsPlayback = false;
	speed = 0.0;
	fly_x = 0.0;
	fly_y = 0.0;
	fly_z = 0.0;
}
/*
	Name:	IsActive
	Parameters in:
			-
	Parameters out:
			-
	Return:
			npc active state
*/
bool CNPC::IsActive()
{
	return status;
}
/*
	Name:	Spawn
	Parameters in:
			-
	Parameters out:
			-
	Return:
			-
*/
void CNPC::Spawn()
{
	if(state == NPC_STATE_PLAYBACK) StopRecordingPlayback(NPC_RECORD_END_REASON_STOP);
	SetHealth(100.0);
	SpawnForWorld(c_player_struct);
	state = NPC_STATE_ONFOOT;
	Spawned(myid);
}
/*
	Name:	Kill
	Parameters in:
			killerid - killer's playerid
			reason - reason of death
	Parameters out:
			-
	Return:
			-
*/
void CNPC::Kill(int killerid,int reason)
{
	if(state == NPC_STATE_PLAYBACK) StopRecordingPlayback(NPC_RECORD_END_REASON_DEATH);
	*(FLOAT*)(c_player_struct + CPlayerHealthOffset) = 0.0;
	if(VisualDeath == 1) KillForWorld(c_player_struct,killerid,reason);
	state = NPC_STATE_DEATH;
	Death(myid,killerid,reason);
}
/*
	Name:	SetPos
	Parameters in:
			x,y,z - coordinates
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetPos(float x,float y,float z)
{
	*(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_POS_X_OFFSET) = x;
	*(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_POS_Y_OFFSET) = y;
	*(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_POS_Z_OFFSET) = z;
	*(FLOAT*)(c_player_struct + CPlayerPosXOffset) = x;
	*(FLOAT*)(c_player_struct + CPlayerPosYOffset) = y;
	*(FLOAT*)(c_player_struct + CPlayerPosZOffset) = z;
}
/*
	Name:	GetPos
	Parameters in:
			-
	Parameters out:
			x,y,z - coordinates
	Return:
			-
*/
void CNPC::GetPos(float* x,float* y,float* z)
{
	*x = *(FLOAT*)(c_player_struct + CPlayerPosXOffset);
	*y = *(FLOAT*)(c_player_struct + CPlayerPosYOffset);
	*z = *(FLOAT*)(c_player_struct + CPlayerPosZOffset);
}
/*
	Name:	SetAngle
	Parameters in:
			angle - facing angle
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetAngle(float angle)
{
	*(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_ANGLE_OFFSET) = angle;
	*(FLOAT*)(c_player_struct + CPlayerAngleOffset) = angle;
}
/*
	Name:	GetAngle
	Parameters in:
			-
	Parameters out:
			-
	Return:
			facing angle
*/
float CNPC::GetAngle()
{
	return *(FLOAT*)(c_player_struct + CPlayerAngleOffset);
}
/*
	Name:	SetVelocity
	Parameters in:
			x,y,z - coordinates
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetVelocity(float x,float y,float z)
{
	*(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_VELOCITY_X_OFFSET) = x;
	*(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_VELOCITY_Y_OFFSET) = y;
	*(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_VELOCITY_Z_OFFSET) = z;
}
/*
	Name:	GetVelocity
	Parameters in:
			-
	Parameters out:
			x,y,z - coordinates
	Return:
			-
*/
void CNPC::GetVelocity(float* x,float* y,float* z)
{
	*x = *(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_VELOCITY_X_OFFSET);
	*y = *(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_VELOCITY_Y_OFFSET);
	*z = *(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_VELOCITY_Z_OFFSET);
}
/*
	Name:	SetCameraPos
	Parameters in:
			x,y,z - coordinates
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetCameraPos(float x,float y,float z)
{
	*(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_POS_X_OFFSET) = x;
	*(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_POS_Y_OFFSET) = y;
	*(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_POS_Z_OFFSET) = z;
	// sync flag
	*(DWORD*)(c_player_struct + CPlayerAimSyncStateOffset) = 1;
}
/*
	Name:	GetCameraPos
	Parameters in:
			-
	Parameters out:
			x,y,z - coordinates
	Return:
			-
*/
void CNPC::GetCameraPos(float* x,float* y,float* z)
{
	*x = *(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_POS_X_OFFSET);
	*y = *(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_POS_Y_OFFSET);
	*z = *(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_POS_Z_OFFSET);
}
/*
	Name:	SetCameraFrontVector
	Parameters in:
			x,y,z - coordinates
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetCameraFrontVector(float x,float y,float z)
{
	*(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_FRONT_VECTOR_X_OFFSET) = x;
	*(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_FRONT_VECTOR_Y_OFFSET) = y;
	*(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_FRONT_VECTOR_Z_OFFSET) = z;
	// sync flag
	*(DWORD*)(c_player_struct + CPlayerAimSyncStateOffset) = 1;
}
/*
	Name:	GetCameraFrontVector
	Parameters in:
			-
	Parameters out:
			x,y,z - coordinates
	Return:
			-
*/
void CNPC::GetCameraFrontVector(float* x,float* y,float* z)
{
	*x = *(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_FRONT_VECTOR_X_OFFSET);
	*y = *(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_FRONT_VECTOR_Y_OFFSET);
	*z = *(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_FRONT_VECTOR_Z_OFFSET);
}
/*
	Name:	SetCameraUpVector
	Parameters in:
			x,y,z - coordinates
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetCameraUpVector(float x,float y,float z)
{
	*(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_UP_VECTOR_X_OFFSET) = x;
	*(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_UP_VECTOR_Y_OFFSET) = y;
	*(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_UP_VECTOR_Z_OFFSET) = z;
	// sync flag
	*(DWORD*)(c_player_struct + CPlayerAimSyncStateOffset) = 1;
}
/*
	Name:	GetCameraUpVector
	Parameters in:
			-
	Parameters out:
			x,y,z - coordinates
	Return:
			-
*/
void CNPC::GetCameraUpVector(float* x,float* y,float* z)
{
	*x = *(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_UP_VECTOR_X_OFFSET);
	*y = *(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_UP_VECTOR_Y_OFFSET);
	*z = *(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_UP_VECTOR_Z_OFFSET);
}
/*
	Name:	SetCameraZAim
	Parameters in:
			angle - camera's Z angle
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetCameraZAim(float angle)
{
	*(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_Z_AIM_OFFSET) = angle;
	// sync flag
	*(DWORD*)(c_player_struct + CPlayerAimSyncStateOffset) = 1;
}
/*
	Name:	GetCameraZAim
	Parameters in:
			-
	Parameters out:
			-
	Return:
			camera's Z angle
*/
float CNPC::GetCameraZAim()
{
	return *(FLOAT*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_Z_AIM_OFFSET);
}
/*
	Name:	SetCameraMode
	Parameters in:
			mode - camera mode
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetCameraMode(int mode)
{
	*(BYTE*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_MODE_OFFSET) = mode;
	// sync flag
	*(DWORD*)(c_player_struct + CPlayerAimSyncStateOffset) = 1;
}
/*
	Name:	GetCameraMode
	Parameters in:
			-
	Parameters out:
			-
	Return:
			camera mode
*/
int CNPC::GetCameraMode()
{
	return (int)(*(BYTE*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_CAMERA_MODE_OFFSET));
}
/*
	Name:	SetWeaponState
	Parameters in:
			wstate - weapon state
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetWeaponState(int wstate)
{
	*(BYTE*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_WEAPON_STATE_OFFSET) = wstate;
	// sync flag
	*(DWORD*)(c_player_struct + CPlayerAimSyncStateOffset) = 1;
}
/*
	Name:	GetWeaponState
	Parameters in:
			-
	Parameters out:
			-
	Return:
			weapon state
*/
int CNPC::GetWeaponState()
{
	return (int)(*(BYTE*)(c_player_struct + CPlayerAimSyncOffset + AIM_SYNC_WEAPON_STATE_OFFSET));
}
/*
	Name:	SetKeys
	Parameters in:
			ud - up or down keys
			lr - left or right keys
			other - other keys
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetKeys(int ud,int lr,int other)
{
	*(unsigned short*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_KEYS_UD_OFFSET) = ud;
	*(unsigned short*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_KEYS_LR_OFFSET) = lr;
	*(unsigned short*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_KEYS_OTHER_OFFSET) = other;
}
/*
	Name:	GetKeys
	Parameters in:
			-
	Parameters out:
			ud - up or down keys
			lr - left or right keys
			other - other keys
	Return:
			-
*/
void CNPC::GetKeys(int* ud,int* lr,int* other)
{
	*ud = (int)*(unsigned short*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_KEYS_UD_OFFSET);
	*lr = (int)*(unsigned short*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_KEYS_LR_OFFSET);
	*other = (int)*(unsigned short*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_KEYS_OTHER_OFFSET);
}
/*
	Name:	SetState
	Parameters in:
			newstate - new npc's state
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetState(int newstate)
{
	state = newstate;
}
/*
	Name:	GetState
	Parameters in:
			-
	Parameters out:
			-
	Return:
			npc's state
*/
int CNPC::GetState()
{
	return state;
}

/*
	Name:	SetSpecialAction
	Parameters in:
			actionid - new npc's special action
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetSpecialAction(int actionid)
{
	*(BYTE*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_SPECTIAL_ACTION_OFFSET) = (BYTE)actionid;
}
/*
	Name:	GetSpecialAction
	Parameters in:
			-
	Parameters out:
			-
	Return:
			npc's special action
*/
int CNPC::GetSpecialAction()
{
	return (int)(*(BYTE*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_SPECTIAL_ACTION_OFFSET));
}
/*
	Name:	SetWeapon
	Parameters in:
			weaponid - new npc's weapon
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetWeapon(int weaponid)
{
	*(BYTE*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_WEAPON_OFFSET) = (BYTE)weaponid;
}
/*
	Name:	GetWeapon
	Parameters in:
			-
	Parameters out:
			-
	Return:
			npc's weapon
*/
int CNPC::GetWeapon()
{
	return (int)(*(BYTE*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_WEAPON_OFFSET));
}
/*
	Name:	SetWeaponSkillLevel
	Parameters in:
			weapontype - npc's weapon
			level - level of skill
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetWeaponSkillLevel(int weapontype,int level)
{
	SetWeaponSkill(c_player_struct,weapontype,level);
}
/*
	Name:	GetWeaponSkillLevel
	Parameters in:
			weapontype - npc's weapon
	Parameters out:
			-
	Return:
			level of skill
*/
int CNPC::GetWeaponSkillLevel(int weapontype)
{
	return (int)*(WORD*)(c_player_struct + CPlayerWeaponSkillOffset + (weapontype * 2));
}
/*
	Name:	SetHealth
	Parameters in:
			health - new npc's health
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetHealth(float health)
{
	*(BYTE*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_HEALTH_OFFSET) = (BYTE)health;
	*(BYTE*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_PLAYER_HEALTH_OFFSET) = (BYTE)health;
	*(FLOAT*)(c_player_struct + CPlayerHealthOffset) = health;
}
/*
	Name:	GetHealth
	Parameters in:
			-
	Parameters out:
			-
	Return:
			npc's health
*/
float CNPC::GetHealth()
{
	return *(FLOAT*)(c_player_struct + CPlayerHealthOffset);
}
/*
	Name:	SetArmour
	Parameters in:
			armour - new npc's armour
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetArmour(float armour)
{
	*(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + INCAR_SYNC_PLAYER_HEALTH_OFFSET) = (BYTE)armour;
	*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_PLAYER_ARMOUR_OFFSET) = (BYTE)armour;
	*(FLOAT*)(c_player_struct + CPlayerArmourOffset) = armour;
}
/*
	Name:	GetArmour
	Parameters in:
			-
	Parameters out:
			-
	Return:
			npc's armour
*/
float CNPC::GetArmour()
{
	return *(FLOAT*)(c_player_struct + CPlayerArmourOffset);
}
/*
	Name:	SetInterior
	Parameters in:
			interior - new npc's interior
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetInterior(int interior)
{
	*(DWORD*)(c_player_struct + CPlayerInteriorOffset) = interior;
}
/*
	Name:	GetInterior
	Parameters in:
			-
	Parameters out:
			-
	Return:
			npc's interior
*/
int CNPC::GetInterior()
{
	return (int)*(DWORD*)(c_player_struct + CPlayerInteriorOffset);
}
/*
	Name:	SetSkin
	Parameters in:
			skin - new npc's skin
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetSkin(int skin)
{
	SetSkinData(myid,skin);
}
/*
	Name:	GetSkin
	Parameters in:
			-
	Parameters out:
			-
	Return:
			npc's skin
*/
int CNPC::GetSkin()
{
	return (int)*(DWORD*)(c_player_struct + CPlayerSkinOffset);
}
/*
	Name:	SetSurfing
	Parameters in:
			x,y,z - coordinates
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetSurfing(float x,float y,float z)
{
	*(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_SURFING_X_OFFSET) = x;
	*(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_SURFING_Y_OFFSET) = y;
	*(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_SURFING_Z_OFFSET) = z;
}
/*
	Name:	GetSurfing
	Parameters in:
			-
	Parameters out:
			x,y,z - coordinates
	Return:
			-
*/
void CNPC::GetSurfing(float* x,float* y,float* z)
{
	*x = *(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_SURFING_X_OFFSET);
	*y = *(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_SURFING_Y_OFFSET);
	*z = *(FLOAT*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_SURFING_Z_OFFSET);
}
/*
	Name:	SetSurfingVehicle
	Parameters in:
			vehicleid - id of vehicle for surfing
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetSurfingVehicle(int vehicleid)
{
	*(WORD*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_SURFING_INFO_OFFSET) = (WORD)vehicleid;
}
/*
	Name:	GetSurfingVehicle
	Parameters in:
			-
	Parameters out:
			x-
	Return:
			surfing vehicle id
*/
int CNPC::GetSurfingVehicle()
{
	return (int)*(WORD*)(c_player_struct + CPlayerFootSyncOffset + FOOT_SYNC_SURFING_INFO_OFFSET);
}
/*
	Name:	SetImpregnable
	Parameters in:
			state - impregnable state
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetImpregnable(bool istate)
{
	impregnable = istate;
}
/*
	Name:	IsImpregnable
	Parameters in:
			-
	Parameters out:
			-
	Return:
			true / false
*/
bool CNPC::IsImpregnable()
{
	return impregnable;
}
/*
	Name:	GoTo
	Parameters in:
			x,y,z - coordinates
			step - dist of step
	Parameters out:
			-
	Return:
			-
*/
void CNPC::GoTo(float x,float y,float z,float step,int use_z_map)
{
	// get pos
	float pos_x,pos_y,pos_z;
	float t_z;
	GetPos(&pos_x,&pos_y,&pos_z);
	// get len
	vX = x - pos_x;
	vY = y - pos_y;
	vZ = z - pos_z;
	g_len = sqrt((vX * vX) + (vY * vY) + (vZ * vZ));
	// get vector
	vX /= g_len;
	vY /= g_len;
	vZ /= g_len;
	// get angle
	t_z = (atan2(vY,vX) * (180.0 / M_PI)) + 270.0;
	if(t_z > 360.0) t_z -= 360.0;
	// set roll	
	SetAngle(t_z);
	// get real speed
	speed = step / 1200;
	// now speed = 1.0 per 50 ms
	// we need speed per 1 min
	// 1 min = 60 sec = 60_000 ms
	// now speed 1.0 per 1/1200 min
	// find new speed: (step / 1200) * v* ? try...
	// get current speed vector
	vX *= speed;
	vY *= speed;
	vZ *= speed;
	// set info
	IsMoving = true;
	IsUseZMap = (bool)use_z_map;
}
/*
	Name:	Stop
	Parameters in:
			-
	Parameters out:
			-
	Return:
			-
*/
void CNPC::Stop()
{
	IsMoving = false;
	speed = 0.0;
}
/*
	Name:	PutInVehicle
	Parameters in:
			vehicleid - id of vehicle
			seat - seat
	Parameters out:
			-
	Return:
			-
*/
void CNPC::PutInVehicle(int vehicleid,int seat)
{
	DWORD c_vehicles = *(DWORD*)(c_samp + C_SAMP_VEHICLES_OFFSET);
	DWORD c_vehicle = *(DWORD*)(c_vehicles + (vehicleid * 4) + C_VEHICLES_VEHICLE_OFFSET);
	if(c_vehicle)
	{
		if(seat == 0)
		{
			*(WORD*)(c_vehicle + CVehicleDriverOffset) = (WORD)myid;
			// player data
			*(WORD*)(c_player_struct + CPlayerVehicleIdOffset) = vehicleid;
			*(BYTE*)(c_player_struct + CPlayerVehicleSeatOffset) = seat;
			// sync data
			*(WORD*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_VEHICLEID_OFFSET) = vehicleid;
			// pos
			*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_POS_X_OFFSET) = *(FLOAT*)(c_vehicle + CVehiclePosXOffset);
			*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_POS_Y_OFFSET) = *(FLOAT*)(c_vehicle + CVehiclePosYOffset);
			*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_POS_Z_OFFSET) = *(FLOAT*)(c_vehicle + CVehiclePosZOffset);
			// health
			*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_HEALTH_OFFSET) = *(FLOAT*)(c_vehicle + CVehicleHealthOffset);
			state = NPC_STATE_DRIVER;
		}
		else
		{
			// player data
			*(WORD*)(c_player_struct + CPlayerVehicleIdOffset) = vehicleid;
			*(BYTE*)(c_player_struct + CPlayerVehicleSeatOffset) = seat;
			// sync data
			*(WORD*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_VEHICLEID_OFFSET) = vehicleid;
			*(BYTE*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_SEAT_OFFSET) = seat;
			*(BYTE*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_DRIVEBY_OFFSET) = 4;
			// pos
			*(FLOAT*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_POS_X_OFFSET) = *(FLOAT*)(c_vehicle + CVehiclePosXOffset);
			*(FLOAT*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_POS_Y_OFFSET) = *(FLOAT*)(c_vehicle + CVehiclePosYOffset);
			*(FLOAT*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_POS_Z_OFFSET) = *(FLOAT*)(c_vehicle + CVehiclePosZOffset);
			state = NPC_STATE_PASSENGER;
		}
	}
}
/*
	Name:	SetVehiclePos
	Parameters in:
			x,y,z - coordinates
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetVehiclePos(float x,float y,float z)
{
	// sync data
	*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_POS_X_OFFSET) = x;
	*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_POS_Y_OFFSET) = y;
	*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_POS_Z_OFFSET) = z;
	// player data
	*(FLOAT*)(c_player_struct + CPlayerPosXOffset) = x;
	*(FLOAT*)(c_player_struct + CPlayerPosYOffset) = y;
	*(FLOAT*)(c_player_struct + CPlayerPosZOffset) = z;
	// vehicle data
	int vehicleid = *(WORD*)(c_player_struct + CPlayerVehicleIdOffset);
	DWORD c_vehicles = *(DWORD*)(c_samp + C_SAMP_VEHICLES_OFFSET);
	DWORD c_vehicle = *(DWORD*)(c_vehicles + (vehicleid * 4) + C_VEHICLES_VEHICLE_OFFSET);
	if(c_vehicle)
	{
		*(FLOAT*)(c_vehicle + CVehiclePosXOffset) = x;
		*(FLOAT*)(c_vehicle + CVehiclePosYOffset) = y;
		*(FLOAT*)(c_vehicle + CVehiclePosZOffset) = z;
		// train fix
		DWORD model = *(DWORD*)(c_vehicle + CVehicleModelOffset);
		if((model == 537) || (model == 538))
		{
			// first trailer
			vehicleid++;
			c_vehicle = *(DWORD*)(c_vehicles + (vehicleid * 4) + C_VEHICLES_VEHICLE_OFFSET);
			if(c_vehicle)
			{
				*(FLOAT*)(c_vehicle + CVehiclePosXOffset) = x;
				*(FLOAT*)(c_vehicle + CVehiclePosYOffset) = y;
				*(FLOAT*)(c_vehicle + CVehiclePosZOffset) = z;
			}
			// second trailer
			vehicleid++;
			c_vehicle = *(DWORD*)(c_vehicles + (vehicleid * 4) + C_VEHICLES_VEHICLE_OFFSET);
			if(c_vehicle)
			{
				*(FLOAT*)(c_vehicle + CVehiclePosXOffset) = x;
				*(FLOAT*)(c_vehicle + CVehiclePosYOffset) = y;
				*(FLOAT*)(c_vehicle + CVehiclePosZOffset) = z;
			}
			// third trailer
			vehicleid++;
			c_vehicle = *(DWORD*)(c_vehicles + (vehicleid * 4) + C_VEHICLES_VEHICLE_OFFSET);
			if(c_vehicle)
			{
				*(FLOAT*)(c_vehicle + CVehiclePosXOffset) = x;
				*(FLOAT*)(c_vehicle + CVehiclePosYOffset) = y;
				*(FLOAT*)(c_vehicle + CVehiclePosZOffset) = z;
			}
		}
		if((vehicleid = GetVehicleTrailer()) != INVALID_VEHICLE_ID)
		{
			c_vehicle = *(DWORD*)(c_vehicles + (vehicleid * 4) + C_VEHICLES_VEHICLE_OFFSET);
			if(c_vehicle)
			{
				*(FLOAT*)(c_vehicle + CVehiclePosXOffset) = x;
				*(FLOAT*)(c_vehicle + CVehiclePosYOffset) = y;
				*(FLOAT*)(c_vehicle + CVehiclePosZOffset) = z;
			}
		}
	}
}
/*
	Name:	GetVehiclePos
	Parameters in:
			-
	Parameters out:
			x,y,z - coordinates
	Return:
			-
*/
void CNPC::GetVehiclePos(float* x,float* y,float* z)
{
	*x = *(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_POS_X_OFFSET);
	*y = *(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_POS_Y_OFFSET);
	*z = *(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_POS_Z_OFFSET);
}
/*
	Name:	SetVehicleRoll
	Parameters in:
			x,y,z - angles
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetVehicleRoll(float x,float y,float z)
{
	*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_ROLL_X_OFFSET) = x;
	*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_ROLL_Y_OFFSET) = y;
	*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_ROLL_Z_OFFSET) = z;
}
/*
	Name:	GetVehicleRoll
	Parameters in:
			-
	Parameters out:
			x,y,z - angles
	Return:
			-
*/
void CNPC::GetVehicleRoll(float* x,float* y,float* z)
{
	*x = *(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_ROLL_X_OFFSET);
	*y = *(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_ROLL_Y_OFFSET);
	*z = *(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_ROLL_Z_OFFSET);
}
/*
	Name:	SetVehicleDirection
	Parameters in:
			x,y,z - coordinates
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetVehicleVelocity(float x,float y,float z)
{
	*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_VELOCITY_X_OFFSET) = x;
	*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_VELOCITY_Y_OFFSET) = y;
	*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_VELOCITY_Z_OFFSET) = z;
}
/*
	Name:	GetVehicleDirection
	Parameters in:
			-
	Parameters out:
			x,y,z - coordinates
	Return:
			-
*/
void CNPC::GetVehicleVelocity(float* x,float* y,float* z)
{
	*x = *(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_VELOCITY_X_OFFSET);
	*y = *(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_VELOCITY_Y_OFFSET);
	*z = *(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_VELOCITY_Z_OFFSET);
}
/*
	Name:	SetVehicleKeys
	Parameters in:
			ud - up or down keys
			lr - left or right keys
			other - other keys
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetVehicleKeys(int ud,int lr,int other)
{
	*(unsigned short*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_KEYS_UD_ANALOG_OFFSET) = ud;
	*(unsigned short*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_KEYS_LR_ANALOG_OFFSET) = lr;
	*(unsigned short*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_KEYS_OTHER_OFFSET) = other;
}
/*
	Name:	GetVehicleKeys
	Parameters in:
			-
	Parameters out:
			ud - up or down keys
			lr - left or right keys
			other - other keys
	Return:
			-
*/
void CNPC::GetVehicleKeys(int* ud,int* lr,int* other)
{
	*ud = (int)*(unsigned short*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_KEYS_UD_ANALOG_OFFSET);
	*lr = (int)*(unsigned short*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_KEYS_LR_ANALOG_OFFSET);
	*other = (int)*(unsigned short*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_KEYS_OTHER_OFFSET);
}
/*
	Name:	SetVehicleSiren
	Parameters in:
			state - new npc's siren state
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetVehicleSiren(int state)
{
	*(BYTE*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_SIREN_OFFSET) = (BYTE)state;
}
/*
	Name:	GetVehicleSiren
	Parameters in:
			-
	Parameters out:
			-
	Return:
			npc's siren state
*/
int CNPC::GetVehicleSiren()
{
	return (int)*(BYTE*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_SIREN_OFFSET);
}
/*
	Name:	SetVehicleHealth
	Parameters in:
			health - new npc's vehicle health
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetVehicleHealth(float health)
{
	*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_HEALTH_OFFSET) = health;
	int vehicleid = *(WORD*)(c_player_struct + CPlayerVehicleIdOffset);
	DWORD c_vehicles = *(DWORD*)(c_samp + C_SAMP_VEHICLES_OFFSET);
	DWORD c_vehicle = *(DWORD*)(c_vehicles + (vehicleid * 4) + C_VEHICLES_VEHICLE_OFFSET);
	if(c_vehicle) *(FLOAT*)(c_vehicle + CVehicleHealthOffset) = health;
}
/*
	Name:	GetVehicleHealth
	Parameters in:
			-
	Parameters out:
			-
	Return:
			npc's vehicle health
*/
float CNPC::GetVehicleHealth()
{
	return *(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_HEALTH_OFFSET);
}
/*
	Name:	SetVehicleUnique
	Parameters in:
			health - new npc's vehicle unique params
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetVehicleUnique(FLOAT unique)
{
	*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_UNIQUE_OFFSET) = unique;
}
/*
	Name:	GetVehicleUnique
	Parameters in:
			-
	Parameters out:
			-
	Return:
			npc's vehicle unique params
*/
float CNPC::GetVehicleUnique()
{
	return *(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_UNIQUE_OFFSET);
}
/*
	Name:	SetVehicleWeapon
	Parameters in:
			weaponid - new npc's weapon in vehicle
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetVehicleWeapon(int weaponid)
{
	*(BYTE*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_CURRENT_WEAPON_OFFSET) = (BYTE)weaponid;
}
/*
	Name:	GetVehicleWeapon
	Parameters in:
			-
	Parameters out:
			-
	Return:
			npc's weapon in vehicle
*/
int CNPC::GetVehicleWeapon()
{
	return (int)*(BYTE*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_CURRENT_WEAPON_OFFSET);
}
/*
	Name:	SetVehicleTrailer
	Parameters in:
			trailer - trailer's id attached to npc's vehicle
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetVehicleTrailer(int trailer)
{
	*(BYTE*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_TRAILER_ID_OFFSET) = (BYTE)trailer;
}
/*
	Name:	GetVehicleTrailer
	Parameters in:
			-
	Parameters out:
			-
	Return:
			trailer's id attached to npc's vehicle
*/
int CNPC::GetVehicleTrailer()
{
	return (int)*(BYTE*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_TRAILER_ID_OFFSET);
}
/*
	Name:	DriveTo
	Parameters in:
			x,y,z - coordinates
			step - dist of step
	Parameters out:
			-
	Return:
			-
*/
void CNPC::DriveTo(float x,float y,float z,float step,int use_z_map)
{
	// get pos
	float pos_x,pos_y,pos_z;
	float /*t_x,t_y,*/t_z;
	GetVehiclePos(&pos_x,&pos_y,&pos_z);
	// get len
	vX = x - pos_x;
	vY = y - pos_y;
	vZ = z - pos_z;
	g_len = sqrt((vX * vX) + (vY * vY) + (vZ * vZ));
	// get vector
	vX /= g_len;
	vY /= g_len;
	vZ /= g_len;
	// get angle
	// x
/*	t_x = (atan2(vY,-vZ) * (180.0 / M_PI)) + 270.0;
	if(t_x > 360.0) t_x -= 360.0;
	// y
	t_y = (atan2(-vZ,vX) * (180.0 / M_PI)) + 270.0;
	if(t_y > 360.0) t_y -= 360.0;
*/	// z
	t_z = (atan2(vY,vX) * (180.0 / M_PI)) + 270.0;
	if(t_z > 360.0) t_z -= 360.0;
	// quaternion
//	Quaternion qua;
//	quaternion_from_angles(&qua,t_x,t_y,t_z);
	// set roll	
	SetVehicleRoll(0.0,0.0,Grad2Roll(t_z));
//	*(FLOAT*)(c_player_struct + CPlayerInCarSyncOffset + INCAR_SYNC_UNKNOWN_OFFSET) = qua.Z;
	// get real velocity
	speed = step / 100;
	// get current velocity vector
	pos_x = vX * speed;
	pos_y = vY * speed;
	pos_z = vZ * speed;
	// set velocity
	SetVehicleVelocity(pos_x,pos_y,pos_z);
	// get real speed
	speed *= 4.0;
	// get current speed vector
	vX *= speed;
	vY *= speed;
	vZ *= speed;
	// set info
	IsMoving = true;
	IsUseZMap = (bool)use_z_map;
}
/*
	Name:	SetPassangerDriveBy
	Parameters in:
			dstate - state of drive by
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetPassangerDriveBy(int dstate)
{
	if(dstate == 1) 
	{
		*(BYTE*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_SEAT_OFFSET) = 129;
		*(BYTE*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_DRIVEBY_OFFSET) = 55;
	}
	else
	{
		*(BYTE*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_SEAT_OFFSET) = *(BYTE*)(c_player_struct + CPlayerVehicleSeatOffset);
		*(BYTE*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_DRIVEBY_OFFSET) = 4;
	}
}
/*
	Name:	GetPassangerDriveBy
	Parameters in:
			-
	Parameters out:
			-
	Return:
			state of drive by
*/
int CNPC::GetPassangerDriveBy()
{
	if(*(BYTE*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_SEAT_OFFSET) == 129) return 1;
	return 0;
}
/*
	Name:	SetPassangerWeapon
	Parameters in:
			weaponid - new npc's weapon
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetPassangerWeapon(int weaponid)
{
	*(BYTE*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_PLAYER_WEAPON_OFFSET) = (BYTE)weaponid;
}
/*
	Name:	GetPassangerWeapon
	Parameters in:
			-
	Parameters out:
			-
	Return:
			npc's weapon
*/
int CNPC::GetPassangerWeapon()
{
	return (int)*(BYTE*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_PLAYER_WEAPON_OFFSET);
}
/*
	Name:	SetPassangerKeys
	Parameters in:
			ud - up or down keys
			lr - left or right keys
			other - other keys
	Parameters out:
			-
	Return:
			-
*/
void CNPC::SetPassangerKeys(int ud,int lr,int other)
{
	*(unsigned short*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_KEYS_UD_OFFSET) = ud;
	*(unsigned short*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_KEYS_LR_OFFSET) = lr;
	*(unsigned short*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_KEYS_OTHER_OFFSET) = other;
}
/*
	Name:	GetPassangerKeys
	Parameters in:
			-
	Parameters out:
			ud - up or down keys
			lr - left or right keys
			other - other keys
	Return:
			-
*/
void CNPC::GetPassangerKeys(int* ud,int* lr,int* other)
{
	*ud = (int)*(unsigned short*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_KEYS_UD_OFFSET);
	*lr = (int)*(unsigned short*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_KEYS_LR_OFFSET);
	*other = (int)*(unsigned short*)(c_player_struct + CPlayerPassangerSyncOffset + PASSANGER_SYNC_KEYS_OTHER_OFFSET);
}
/*
	Name:	StartRecordingPlayback
	Parameters in:
			name - name of file
	Parameters out:
			-
	Return:
			1 / 0
*/
int CNPC::StartRecordingPlayback(char* name)
{
	if(!IsPlayback)
	{
		char* buf = new char[128];
		// path
		sprintf(buf,"scriptfiles/%s.rec",name);
		// open
		PlaybackFile = fopen(buf,"rb");
		if(PlaybackFile)
		{
			StartTime = GetTickCount();
			// read main info
			DWORD tmp;

			fread(&tmp,1,4,PlaybackFile);
			fread(&PlaybackType,1,4,PlaybackFile);
			// read one block
			switch(PlaybackType)
			{
			case PLAYER_RECORDING_TYPE_DRIVER:
				{
					fread(&CurrentBlockTime,1,4,PlaybackFile);
					fread(&CurrentBlockInCarData,1,sizeof(InCarSync),PlaybackFile);
					break;
				}
			case PLAYER_RECORDING_TYPE_ONFOOT:
				{
					fread(&CurrentBlockTime,1,4,PlaybackFile);
					fread(&CurrentBlockOnFootData,1,sizeof(OnFootSync),PlaybackFile);
					break;
				}
			}
			state = NPC_STATE_PLAYBACK;
			IsPlayback = true;
			return 1;
		}
	}
	return 0;
}
/*
	Name:	ReadNextPlaybackBlock
	Parameters in:
			-
	Parameters out:
			-
	Return:
			-
*/
void CNPC::ReadNextPlaybackBlock()
{
	if(PlaybackFile)
	{
		if(feof(PlaybackFile))
		{
			StopRecordingPlayback(NPC_RECORD_END_REASON_END);	
		}
		else
		{
			switch(PlaybackType)
			{
			case PLAYER_RECORDING_TYPE_DRIVER:
				{
					fread(&CurrentBlockTime,1,4,PlaybackFile);
					fread(&CurrentBlockInCarData,1,sizeof(InCarSync),PlaybackFile);
					break;
				}
			case PLAYER_RECORDING_TYPE_ONFOOT:
				{
					fread(&CurrentBlockTime,1,4,PlaybackFile);
					fread(&CurrentBlockOnFootData,1,sizeof(OnFootSync),PlaybackFile);
					break;
				}
			}
		}
	}
}
/*
	Name:	PauseRecordingPlayback
	Parameters in:
			-
	Parameters out:
			-
	Return:
			-
*/
void CNPC::PauseRecordingPlayback()
{
	if(IsPlayback)
	{
		switch(PlaybackType)
		{
		case PLAYER_RECORDING_TYPE_DRIVER:
			{
				SetVehicleVelocity(0.0,0.0,0.0);
				state = NPC_STATE_DRIVER;
				break;
			}
		case PLAYER_RECORDING_TYPE_ONFOOT:
			{
				SetVelocity(0.0,0.0,0.0);
				state = NPC_STATE_ONFOOT;
				break;
			}
		}
		StartTime -= GetTickCount();
	}
}
/*
	Name:	ContinueRecordingPlayback
	Parameters in:
			-
	Parameters out:
			-
	Return:
			-
*/
void CNPC::ContinueRecordingPlayback()
{
	if(IsPlayback)
	{
		state = NPC_STATE_PLAYBACK;
		StartTime += GetTickCount();
	}
}
/*
	Name:	StopRecordingPlayback
	Parameters in:
			-
	Parameters out:
			-
	Return:
			-
*/
void CNPC::StopRecordingPlayback(int reason)
{
	if(IsPlayback)
	{
		switch(PlaybackType)
		{
		case PLAYER_RECORDING_TYPE_DRIVER:
			{
				SetVehicleKeys(0,0,0);
				SetVehicleVelocity(0.0,0.0,0.0);
				state = NPC_STATE_DRIVER;
				break;
			}
		case PLAYER_RECORDING_TYPE_ONFOOT:
			{
				SetKeys(0,0,0);
				SetVelocity(0.0,0.0,0.0);
				state = NPC_STATE_ONFOOT;
				break;
			}
		}
		fclose(PlaybackFile);

		StartTime = 0;
		PlaybackFile = 0;
		IsPlayback = false;

		PlaybackEnd(myid,reason);
	}
}
/*
	Name:	Sync
	Parameters in:
			-
	Parameters out:
			-
	Return:
			-
*/
void CNPC::Sync()
{
	switch(state)
	{
	case NPC_STATE_ONFOOT:
		{
			int id = GetSurfingVehicle();
			if(id != INVALID_VEHICLE_ID)
			{
				DWORD c_vehicles = *(DWORD*)(c_samp + C_SAMP_VEHICLES_OFFSET);
				DWORD c_vehicle = *(DWORD*)(c_vehicles + (id * 4) + C_VEHICLES_VEHICLE_OFFSET);
				
				if(c_vehicle)
				{
					*(FLOAT*)(c_player_struct + CPlayerPosXOffset) = *(FLOAT*)(c_vehicle + CVehiclePosXOffset);
					*(FLOAT*)(c_player_struct + CPlayerPosYOffset) = *(FLOAT*)(c_vehicle + CVehiclePosYOffset);
					*(FLOAT*)(c_player_struct + CPlayerPosZOffset) = *(FLOAT*)(c_vehicle + CVehiclePosZOffset);
				}
			}

			if(IsMoving)
			{
				// get current pos
				float x,y,z;
				GetPos(&x,&y,&z);
				// move coords
				x += vX;
				y += vY;
				if(IsUseZMap) z = ZMap->GetZForCoords(x,y) + Z_CORRECT;
				else z += vZ;
				// set coords
				SetPos(x,y,z);
				g_len -= speed;
				if(g_len <= 0.0)
				{
					Stop();
					SetKeys(0,0,0);
					// callback
					MovingComplete(myid);
				}
			}
			if((fly_x != 0.0) || (fly_y != 0.0) || (fly_z != 0.0))
			{
				if(sqrt((fly_x * fly_x) + (fly_y * fly_y) + (fly_z * fly_z)) < 0.1)
				{
					fly_x = 0.0;
					fly_y = 0.0;
					fly_z = 0.0;
					if(ZMap)
					{
						float x,y,z;
						GetPos(&x,&y,&z);
						SetPos(x,y,ZMap->GetZForCoords(x,y) + Z_CORRECT);
					}
				}
				float x,y,z;
				GetPos(&x,&y,&z);
				// moving
				x += fly_x;
				y += fly_y;
				z += fly_z;
				// set coords
				if(ZMap)
				{
					if(ZMap->GetZForCoords(x,y) <= z) SetPos(x,y,z);
					else
					{
						fly_x = 0.0;
						fly_y = 0.0;
						fly_z = 0.0;
					}
				}
				else SetPos(x,y,z);
				// less velocity
				fly_x /= 1.05;
				fly_y /= 1.05;
				fly_z /= 1.05;
			}
			*(DWORD*)(c_player_struct + CPlayerSyncTypeOffset) = UPDATE_TYPE_ONFOOT;
			*(DWORD*)(c_player_struct + CPlayerStateOffset) = PLAYER_STATE_ONFOOT;
			break;
		}
	case NPC_STATE_DRIVER:
		{
			if(IsMoving)
			{
				// get current pos
				float x,y,z;
				GetVehiclePos(&x,&y,&z);
				// move coords
				x += vX;
				y += vY;
				if(IsUseZMap) z = ZMap->GetZForCoords(x,y) + Z_CORRECT;
				else z += vZ;
				// set coords
				SetVehiclePos(x,y,z);
				g_len -= speed;
				if(g_len <= 0.0)
				{
					Stop();
					SetVehicleVelocity(0.0,0.0,0.0);
					SetVehicleKeys(0,0,0);
					// callback
					MovingComplete(myid);
				}
			}
			*(DWORD*)(c_player_struct + CPlayerSyncTypeOffset) = UPDATE_TYPE_INCAR;
			*(DWORD*)(c_player_struct + CPlayerStateOffset) = PLAYER_STATE_DRIVER;
			break;
		}
	case NPC_STATE_PASSENGER:
		{
			*(DWORD*)(c_player_struct + CPlayerSyncTypeOffset) = UPDATE_TYPE_PASSENGER;
			*(DWORD*)(c_player_struct + CPlayerStateOffset) = PLAYER_STATE_PASSENGER;
			break;
		}
	case NPC_STATE_DEATH:
		{
			*(DWORD*)(c_player_struct + CPlayerSyncTypeOffset) = UPDATE_TYPE_ONFOOT;
			*(DWORD*)(c_player_struct + CPlayerStateOffset) = PLAYER_STATE_ONFOOT;
			break;
		}
	case NPC_STATE_PLAYBACK:
		{
			if((GetTickCount() - StartTime) >= CurrentBlockTime)
			{
				switch(PlaybackType)
				{
				case PLAYER_RECORDING_TYPE_DRIVER:
					{
						// set data
						SetVehiclePos(CurrentBlockInCarData.PosX,CurrentBlockInCarData.PosY,CurrentBlockInCarData.PosZ);
						SetVehicleRoll(CurrentBlockInCarData.RollX,CurrentBlockInCarData.RollY,CurrentBlockInCarData.RollZ);
						SetVehicleVelocity(CurrentBlockInCarData.VelocityX,CurrentBlockInCarData.VelocityY,CurrentBlockInCarData.VelocityZ);
						SetVehicleKeys(CurrentBlockInCarData.KeysUD,CurrentBlockInCarData.KeysLR,CurrentBlockInCarData.KeysOther);
						SetVehicleHealth(CurrentBlockInCarData.Health);
						SetVehicleSiren((int)CurrentBlockInCarData.SirenState);
						SetVehicleUnique(CurrentBlockInCarData.Unique);
						SetVehicleWeapon((int)CurrentBlockInCarData.PlayerWeapon);
						// apply to sync
						*(DWORD*)(c_player_struct + CPlayerSyncTypeOffset) = UPDATE_TYPE_INCAR;
						*(DWORD*)(c_player_struct + CPlayerStateOffset) = PLAYER_STATE_DRIVER;
						break;
					}
				case PLAYER_RECORDING_TYPE_ONFOOT:
					{
						// set data
						SetPos(CurrentBlockOnFootData.PosX,CurrentBlockOnFootData.PosY,CurrentBlockOnFootData.PosZ);
						SetAngle(CurrentBlockOnFootData.Angle);
						SetVelocity(CurrentBlockOnFootData.VelocityX,CurrentBlockOnFootData.VelocityY,CurrentBlockOnFootData.VelocityZ);
						SetKeys(CurrentBlockOnFootData.KeysUD,CurrentBlockOnFootData.KeysLR,CurrentBlockOnFootData.KeysOther);
						SetSurfing(CurrentBlockOnFootData.SurfingX,CurrentBlockOnFootData.SurfingY,CurrentBlockOnFootData.SurfingZ);
						SetSpecialAction(CurrentBlockOnFootData.SpecialAction);
						SetWeapon((int)CurrentBlockOnFootData.PlayerWeapon);
						// apply to sync
						*(DWORD*)(c_player_struct + CPlayerSyncTypeOffset) = UPDATE_TYPE_ONFOOT;
						*(DWORD*)(c_player_struct + CPlayerStateOffset) = PLAYER_STATE_ONFOOT;
						break;
					}
				}
				// read next block
				ReadNextPlaybackBlock();
			}	
			break;
		}
	}
}

/*
	Name:	WeaponDamage
	Parameters in:
			a_id - attacker id
			cp_* - camera pos
			f_* - camera fron vector 
			health - health of npc
			weapon - weapon id of player
			type - type of fire
	Parameters out:
			-
	Return:
			1 - if for one npc
			0 - if for all
*/
int CNPC::WeaponDamage(int a_id,float cp_x,float cp_y,float cp_z,float f_x,float f_y,float f_z,float health,int weapon,int type)
{
	// npc pos
	GetPos(&np_x,&np_y,&np_z);
	// get len
	tmp_x = np_x - cp_x;
	tmp_y = np_y - cp_y;
	tmp_z = np_z - cp_z;
	d_len = sqrt((tmp_x * tmp_x) + (tmp_y * tmp_y) + (tmp_z * tmp_z));
	// switch type
	switch(type)
	{
	case DAMAGE_TYPE_RAKET:
		{
			// get coords for range
			tmp_x = np_x - (cp_x + (d_len * f_x)); 
			tmp_y = np_y - (cp_y + (d_len * f_y)); 
			tmp_z = np_z - (cp_z + (d_len * f_z)); 
			// part
			if(IsInRange(tmp_x,tmp_y,tmp_z,5.0)) part = BODYPART_ALL;
			else part = -1;
			break;
		}
	case DAMAGE_TYPE_GRENADE:
		{
			if(IsInRange((np_x - cp_x),(np_y - cp_y),(np_z - cp_z),5.0)) part = BODYPART_ALL;
			else part = -1;
			break;
		}
	case DAMAGE_TYPE_MEELE:
		{
			if(IsInRange(tmp_x,tmp_y,tmp_z,0.5)) part = BODYPART_ALL;
			else part = -1;
			break;
		}
	case DAMAGE_TYPE_BULLET:
		{
			// get coords for range
			tmp_x = np_x - (cp_x + (d_len * f_x)); 
			tmp_y = np_y - (cp_y + (d_len * f_y)); 
			tmp_z = cp_z + (d_len * f_z); 
			// part
			if(IsInRange(tmp_x,tmp_y,((np_z + 0.8) - tmp_z),0.15)) part = BODYPART_HEAD;
			else if(IsInRange(tmp_x,tmp_y,((np_z + 0.4) - tmp_z),0.3)) part = BODYPART_TORSO;
			else if(IsInRange(tmp_x,tmp_y,((np_z - 0.4) - tmp_z),0.5)) part = BODYPART_FOOT;
			else part = -1;
			break;
		}
	default:
		{
			part = -1;
			break;
		}
	}

	if(part != -1)
	{
		health -= WeaponsDamage[weapon];
		if(GetDamage(myid,a_id,WeaponsDamage[weapon],part))
		{
			SetHealth(health);
			if(health <= 0.0) Kill(a_id,weapon);
		}
		if(part != BODYPART_ALL) return 1;
	}
	return 0;
}
/*
	Name:	VehicleDamage
	Parameters in:
			a_id - attacker id
			cp_* - camera pos
			f_* - camera fron vector 
			health - health of npc
			weapon - weapon id of player
			type - type of fire
	Parameters out:
			-
	Return:
			1 - if for one npc
			0 - if for all
*/
int CNPC::VehicleDamage(int a_id,float cp_x,float cp_y,float cp_z,float f_x,float f_y,float f_z,float health,int weapon,int type)
{
	// npc pos
	GetPos(&np_x,&np_y,&np_z);
	// get len
	tmp_x = np_x - cp_x;
	tmp_y = np_y - cp_y;
	tmp_z = np_z - cp_z;
	d_len = sqrt((tmp_x * tmp_x) + (tmp_y * tmp_y) + (tmp_z * tmp_z));
	// switch type
	switch(type)
	{
	case 1: // boom
		{
			// get coords for range
			tmp_x = np_x - (cp_x + (d_len * f_x)); 
			tmp_y = np_y - (cp_y + (d_len * f_y)); 
			tmp_z = np_z - (cp_z + (d_len * f_z)); 
			// part
			if(IsInRange(tmp_x,tmp_y,tmp_z,5.0)) part = BODYPART_ALL;
			else part = -1;
			break;
		}
	case 2: // bullet by driver
		{
			// get coords for range
			tmp_x = np_x - (cp_x + (d_len * f_x)); 
			tmp_y = np_y - (cp_y + (d_len * f_y)); 
			tmp_z = np_z - (cp_z + (d_len * f_z)); 
			// part
			if(IsInRange(tmp_x,tmp_y,tmp_z,1.0)) part = BODYPART_ALL;
			else part = -1;
			break;
		}
	case 3: // bullet by passanger
		{
			// get coords for range
			tmp_x = np_x - (cp_x + (d_len * f_x)); 
			tmp_y = np_y - (cp_y + (d_len * f_y)); 
			tmp_z = cp_z + (d_len * f_z); 
			// part
			if(IsInRange(tmp_x,tmp_y,((np_z + 0.8) - tmp_z),0.15)) part = BODYPART_HEAD;
			else if(IsInRange(tmp_x,tmp_y,((np_z + 0.4) - tmp_z),0.3)) part = BODYPART_TORSO;
			else if(IsInRange(tmp_x,tmp_y,((np_z - 0.4) - tmp_z),0.5)) part = BODYPART_FOOT;
			else part = -1;
			break;
		}
	default:
		{
			part = -1;
			break;
		}
	}

	if(part != -1)
	{
		health -= WeaponsDamage[weapon];
		if(GetDamage(myid,a_id,WeaponsDamage[weapon],part))
		{
			SetHealth(health);
			if(health <= 0.0) Kill(a_id,weapon);
		}
		if(part != BODYPART_ALL) return 1;
	}
	return 0;
}

/*
	Name:	VehicleKnock
	Parameters in:
			pos_* - pos of attacker
			v_* - velocity vector
	Parameters out:
			-
	Return:
			-
*/
void CNPC::VehicleKnock(int a_id,float pos_x,float pos_y,float pos_z,float v_x,float v_y,float v_z)
{
	if((fly_x != 0.0) || (fly_y != 0.0) || (fly_z != 0.0)) return;
	// npc pos
	GetPos(&np_x,&np_y,&np_z);
	pos_x += (v_x * 5) - np_x;
	pos_y += (v_y * 5) - np_y;
	pos_z += (v_z * 5) - np_z;
	// if range
	if(IsInRange(pos_x,pos_y,pos_z,1.0))
	{
		if(sqrt((v_x * v_x) + (v_y * v_y) + (v_z * v_z)) < 0.1) return;
		fly_x = v_x * 2;
		fly_y = v_y * 2;
		fly_z = v_z * 2;
		// less health
		float health = GetHealth();
		float dmg = sqrt((fly_x * fly_x) + (fly_y * fly_y) + (fly_z * fly_z)) * 20;
		health -= dmg;
		if(GetDamage(myid,a_id,dmg,4))
		{
			SetHealth(health);
			if(health <= 0.0) Kill(a_id,47);
		}
	}
}